﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
using System.Linq;
using System.Text.RegularExpressions;
using Pyramid.Models;

namespace Pyramid.Bll
{
	public class BllBase
	{
		private PyramidDbContext _db;

		public PyramidDbContext Db
		{
			get { return _db ?? (_db = new PyramidDbContext()); }
		}

		public string Message { get; set; }

		protected void Alert(string msg)
		{
			Message = msg;
		}

		protected string GetConnectionString()
		{
			return ConfigurationManager.ConnectionStrings["PyramidDbContext"].ConnectionString;
		}

		/// <summary>
		/// 获取 model 对应的表名称
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		protected string GetTableName<T>() where T : class
		{
			var objectContext = ((IObjectContextAdapter) Db).ObjectContext;
			var sql = objectContext.CreateObjectSet<T>().ToTraceString();
			var regex = new Regex("FROM (?<table>.*) AS");
			var match = regex.Match(sql);
			var table = match.Groups["table"].Value;
			return table;
		}

		/// <summary>
		/// 批量插入
		/// </summary>
		protected void BulkInsert<T>(IList<T> list) where T : class
		{
			BulkInsert<T, T>(list);
		}

		/// <summary>
		/// 批量插入
		/// </summary>
		protected void BulkInsert<TDto, TEntity>(IList<TDto> list) where TEntity : class
		{
			using (var bulkCopy = new SqlBulkCopy(GetConnectionString()))
			{
				bulkCopy.BatchSize = list.Count;
				bulkCopy.DestinationTableName = GetTableName<TEntity>();

				var table = new DataTable();
				var props = TypeDescriptor.GetProperties(typeof (TDto))
					//Dirty hack to make sure we only have system data types 
					//i.e. filter out the relationships/collections
				                          .Cast<PropertyDescriptor>()
				                          .Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
				                          .ToArray();

				foreach (var propertyInfo in props)
				{
					bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name);
					table.Columns.Add(propertyInfo.Name, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
				}

				var values = new object[props.Length];
				foreach (var item in list)
				{
					for (var i = 0; i < values.Length; i++)
					{
						values[i] = props[i].GetValue(item);
					}

					table.Rows.Add(values);
				}

				bulkCopy.WriteToServer(table);
			}
		}
	}
}